package net.lab1024.sa.gateway.handler;

import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.gateway.dto.ApiProcessDTO;
import net.lab1024.sa.gateway.processor.AbstractApiProcessor;
import net.lab1024.sa.gateway.processor.ExecuteProcessor;
import net.lab1024.sa.gateway.processor.GlobalRateLimitProcessor;
import net.lab1024.sa.gateway.processor.ParamProcessor;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.LinkedHashSet;

/**
 * 责任链构建与入口
 */
@Slf4j
@Component
public class GatewayCoreHandler {

    private final AbstractApiProcessor firstProcessor;

    // 构造责任链（通过构造函数注入处理器）
    public GatewayCoreHandler(GlobalRateLimitProcessor rateLimitProcessor,
                              ParamProcessor paramProcessor,
                              ExecuteProcessor executeProcessor) {
        // 构建链：限流 → 参数校验 → 执行
        rateLimitProcessor.setNextProcessor(paramProcessor);
        paramProcessor.setNextProcessor(executeProcessor);
        this.firstProcessor = rateLimitProcessor;
    }

    // 统一请求入口
    public Mono<Object> handle(ServerWebExchange exchange) {
        String path = exchange.getRequest().getPath().value();
        // 获取原始请求路径，避免StripPrefix过滤器的影响
        LinkedHashSet<URI> originalUris = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
        String originalPath = (originalUris != null && !originalUris.isEmpty())
                ? originalUris.iterator().next().getRawPath()
                : exchange.getRequest().getURI().getRawPath();
        String method = exchange.getRequest().getMethod().name();

        // /admin/**路径走正常的路由转发
        if (originalPath.startsWith("/admin/")) {
            return Mono.empty(); // 返回空Mono表示不处理
        }

        // 只处理/api/**路径的请求
        log.info("开始处理API请求: {} {}", method, path);
        ApiProcessDTO dto = new ApiProcessDTO();
        dto.setExchange(exchange);
        dto.setApiKey(path); // 提取API路径作为标识

        return firstProcessor.process(dto) // 执行责任链
                .then(Mono.defer(() -> {
                    if (dto.getError() != null) {
                        log.error("API处理出错: {} {}, 错误: {}", method, path, dto.getError().getMessage());
                        return Mono.error(dto.getError());
                    }

                    log.info("API处理完成: {} {}, 结果: {}", method, path, dto.getResult());
                    return Mono.just(dto.getResult()); // 返回处理结果
                }));
    }

}